package com.qf.filter;

import com.alibaba.fastjson.JSON;
import com.qf.pojo.Result;
import com.qf.utils.JwtUtils;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;

/**
 * UsernamePasswordAuthenticationFilter 这个过滤器专门用来处理 /login请求的过滤器。内部处理完请求后，如果是登录成功，会将用户信息存入session中
 * 现在我们的需求是将用户登录后的状态信息保存到浏览器端。所以我们要改写UsernamePasswordAuthenticationFilter逻辑
 */
public class LoginFilter extends UsernamePasswordAuthenticationFilter {

    public LoginFilter(AuthenticationManager authenticationManager) {
        super(authenticationManager);
    }

    /**
     * 当用户名和密码校验成功后，回调的方法。这个方法内部的原始逻辑是将用户信息保存到session中
     * @param request
     * @param response
     * @param chain
     * @param authResult
     * @throws IOException
     * @throws ServletException
     */
    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
        //jwt:头部、载荷(用户名、权限)、签名
        User user = (User) authResult.getPrincipal();
        //用户名
        String username = user.getUsername();
        //该用户的权限
        Collection<GrantedAuthority> authorities = user.getAuthorities();

        //将权限对象转换成字符串形式
        List roles = new ArrayList();
        for (GrantedAuthority authority : authorities) {
            String auth = authority.getAuthority();
            roles.add(auth);
        }

        //生成jwt串
        Map claims = new HashMap();
        claims.put("username",username);
        claims.put("roles",roles);
        String token = JwtUtils.createToken(claims, username);

        Result success = Result.success(token);
        response.getWriter().write(JSON.toJSONString(success));
    }

    /**
     * 当用户名和密码校验失败后，回调的方法。这个方法内部的原始逻辑是跳转到security默认的登录页
     * @param request
     * @param response
     * @param failed
     * @throws IOException
     * @throws ServletException
     */
    @Override
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {
        Result result = Result.error(Result.ERROR, "用户名或密码错误");

        String json = JSON.toJSONString(result);

        response.setContentType("text/html;charset=utf-8");
        response.getWriter().write(json);
    }
}
